package com.clp.protocol.modbus_tcp.mb_frame.mb_body.mb_data.req;

import com.clp.protocol.core.utils.ByteUtil;
import com.clp.protocol.modbus_tcp.definition.CoilStatus;
import com.clp.protocol.modbus_tcp.definition.MbByteOrder;
import com.clp.protocol.modbus_tcp.mb_frame.mb_body.mb_data.ReqMbData;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.nio.ByteOrder;
import java.util.List;
import java.util.Objects;

@Getter
@NoArgsConstructor
public class ForceMultiCoilsReqMbData implements ReqMbData {
    /**
     * 设置的起始地址
     */
    private int startAddr;
    /**
     * 设置的数量
     */
    private int num;
    /**
     * 字节计数
     */
    private int byteCount;
    /**
     * 设置内容
     */
    private List<CoilStatus> coilStatuses;

    public ForceMultiCoilsReqMbData(int startAddr, List<CoilStatus> coilStatuses) {
        this.startAddr = startAddr;
        this.num = coilStatuses.size();
        this.byteCount = coilStatuses.size() % 8 == 0 ? (coilStatuses.size() / 8) : (coilStatuses.size() / 8 + 1);
        this.coilStatuses = coilStatuses;
    }

    @Override
    public ReqMbData initBy(ByteBuf buf) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isValid() {
        if (startAddr < 0 || startAddr > 0xFFFF) return false;
        if (coilStatuses == null || coilStatuses.size() > 0xFFFF) return false;
        if (num != coilStatuses.size()) return false;
        return byteCount >= 0 && byteCount * 8 >= coilStatuses.size();
    }

    @Override
    public void writeTo(ByteBuf buf) {
        // 设置起始地址
        buf.writeBytes(MbByteOrder.startAddrOrder == ByteOrder.BIG_ENDIAN ?
                ByteUtil.intToBytes2BE(startAddr) : ByteUtil.intToBytes2LE(startAddr));
        // 设置数量
        buf.writeBytes(MbByteOrder.numOrder == ByteOrder.BIG_ENDIAN ?
                ByteUtil.intToBytes2BE(num) : ByteUtil.intToBytes2LE(num));
        // 字节计数
        buf.writeByte(byteCount);
        // 设置内容
        byte[] coilBytes = new byte[byteCount];
        int index = 0;
        for (int i = 0; i < coilBytes.length; i++) {
            coilBytes[i] = 0;
            for (int j = 0; j < 8; j++) {
                if (index == coilStatuses.size()) {
                    break;
                }
                coilBytes[i] = (byte) ((coilBytes[i] >> 1) & 0x7F);
                coilBytes[i] |= coilStatuses.get(index).getVal() == 1 ? 0x80 : 0x00;
                index += 1;
            }
            if (index % 8 != 0) {
                coilBytes[i] = (byte) (coilBytes[i] >> (8 - (index % 8)) & 0x7F);
            }
        }
        buf.writeBytes(coilBytes);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("设置起始地址：" + startAddr + ", 设置的数量：" + num + ", 字节计数：" + byteCount + ", 设置线圈状态列表：");
        for (int i = 0; i < coilStatuses.size(); i++) {
            if (i % 8 == 0) {
                sb.append(" ");
            }
            sb.append(coilStatuses.get(i).getVal());
        }
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ForceMultiCoilsReqMbData that = (ForceMultiCoilsReqMbData) o;
        return startAddr == that.startAddr && num == that.num && byteCount == that.byteCount && Objects.equals(coilStatuses, that.coilStatuses);
    }

    @Override
    public int hashCode() {
        return Objects.hash(startAddr, num, byteCount, coilStatuses);
    }
}
